﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nine.Animations;
using Microsoft.Xna.Framework.Graphics;
using Nine.Graphics;
using Nine.Graphics.Effects;
using Microsoft.Xna.Framework;
using BEPUphysics.Paths.PathFollowing;
using BEPUphysics.Entities;
using BEPUphysics.Entities.Prefabs;
using BEPUphysics;
using EventFlowLibrary.GameStructure;
using BEPUphysics.DataStructures;
using BEPUphysics.MathExtensions;
using Microsoft.Xna.Framework.Content;
using BEPUphysics.CollisionShapes;

namespace EventFlowLibrary.LevelComponents
{
    internal sealed class AnimatedModel : BaseModel
    {
        internal ModelSkeleton modelSkeleton;

        //public Cylinder movingEntity;
        Space containerSpace;
        /// <summary>
        /// Class allowing us to move an entity and it's collision info in Bepu.
        /// </summary>
        //private EntityMover entityMover;
        MobileMesh mobileMesh;

        internal AnimatedModel(string _id, Model _model, LinkedEffect _linkedEffect, Model _boundsModel, Space _containerSpace, Vector3 _scale, Vector3 _rotation, Vector3 _position)
            : base(_id, _model, _scale, _rotation, _position)
        {
            modelSkeleton = new ModelSkeleton(_model);

            containerSpace = _containerSpace;
            //movingEntity = new Cylinder(Position, TransformedBoundingBox.Max.Y, Math.Max(((TransformedBoundingBox.Max.X - TransformedBoundingBox.Min.X) / 2), ((TransformedBoundingBox.Max.Z - TransformedBoundingBox.Min.Z) / 2)) / 2, 1);
            //movingEntity.Tag = "Model_" + ID;
            //entityMover = new EntityMover(movingEntity);
            //containerSpace.Add(movingEntity);
            //containerSpace.Add(entityMover);

            // hacks hacks hacks
            Vector3[] vertices;
            int[] indices;
            Vector3 newScale = TransformedBoundingBox.Max - TransformedBoundingBox.Min;
            newScale /= 10;
            

            if (_id.Contains("PLincoln"))
            {
                newScale *= 2;
            }
            else
            {
                newScale.Y *= 2;
            }

            //Create a big hollow sphere (squished into an ellipsoid).
            TriangleMesh.GetVerticesAndIndicesFromModel(_boundsModel, out vertices, out indices);
            var transform = new AffineTransform(newScale, Quaternion.Identity, Position);
            mobileMesh = new MobileMesh(vertices, indices, transform, MobileMeshSolidity.Solid);
            mobileMesh.Tag = "Model_" + ID;
            containerSpace.Add(mobileMesh);


            _linkedEffect.EnableDefaultLighting();

            // TODO copied from levelsupport loadshadowmap
            // Set our amibient color. TODO match skybox TODO make shadow static so we don't get flickering.
            IAmbientLight ambientLightEffect = _linkedEffect.Find<IAmbientLight>();
            ambientLightEffect.AmbientLightColor = new Vector3(0.25f, 0.25f, 0.25f);

            IDirectionalLight directionalLight = _linkedEffect.Find<IDirectionalLight>();
            directionalLight.DiffuseColor = Vector3.One * .5f;// todo make this tmatch our skybox
            directionalLight.SpecularColor = Vector3.One * .5f;
            directionalLight.Direction = -Vector3.Normalize(new Vector3(60, 200, 20));// todo this is trying to match the offset of our shadow, make sure is correct. Tested: looks correct with shadows off, now tie to shadow direction.

            
            DisplayModel.ConvertEffectTo(_linkedEffect);
        }

        internal override void SetPosition(Vector3 _position)
        {
            base.SetPosition(_position);

            //mobileMesh.Position = _position;
            mobileMesh.WorldTransform = base.WorldMatrix;

            //entityMover.TargetPosition = _position;
        }

        internal override void SetRotation(Vector3 _rotation)
        {
            base.SetRotation(_rotation);

            mobileMesh.WorldTransform = base.WorldMatrix;
        }

        internal override void SetScale(Vector3 _scale)
        {
            base.SetScale(_scale);

            mobileMesh.WorldTransform = base.WorldMatrix;
        }
    }
}
